#include "id3.h"

void read_image(char *mp3, unsigned char **image, int *image_size) {
    int pipefd[2];
    if (pipe(pipefd) < 0) {
        fprintf(stderr, "error opening pipe\n");
        return;
    }

    pid_t pid;
    pid = fork();
    if (pid < (pid_t) 0) {
        fprintf(stderr, "cannot fork\n");
        return;
    /* child process */
    } else if (pid == (pid_t) 0) {
        /* close read end */
        close(pipefd[0]);

        /* redirect stdout */
        if (dup2(pipefd[1], STDOUT_FILENO) < 0) {
            fprintf(stderr, "child: error duplicating file descriptor\n");
            exit(EXIT_FAILURE);
        }

        /* exec id3-extract-cover */
        if (execlp("id3-extract-cover", "id3-extract-cover", mp3, NULL) < 0) {
            fprintf(stderr, "child: error starting id3-extract cover process\n");
            exit(EXIT_FAILURE);
        }
    /* parent process */
    } else {
        /* close write end */
        close(pipefd[1]);

        /* prepare to read */
        FILE *stream = fdopen(pipefd[0], "r");

        int total = 0, read, image_pos = 0;
        *image_size = 4096;
        *image = malloc(*image_size);
        unsigned char buf[*image_size];
        while ((read = fread(buf, 1, sizeof(buf), stream)) > 0) {
            /* in case we need to allocate more memory, do so */
            if (read > *image_size - image_pos) {
                /* double previous size */
                *image_size *= 2;
                *image = realloc(*image, *image_size);
                if (*image == NULL) {
                    fprintf(stderr, "error reallocating memory for image\n");
                    exit(EXIT_FAILURE);
                }
            }

            if (DEBUG)
                printf("read %i + total %i < image_size %i\n", read, total, *image_size);

            /* transfer newly read bytes */
            assert(read + total <= *image_size);
            for (int i = 0; image_pos < read + total;) {
                (*image)[image_pos] = buf[i];
                ++image_pos;
                ++i;
            }
            
            /* tally total */
            total += read;
        }

        if (DEBUG)  {
            printf("finished the whole ordeal lol, read %i bytes\n", total);
            printf("image has %i bytes with pos %i\n", *image_size, image_pos);
        }

        /* at the end get rid of excessive memory */
        if (image_pos > 0 && image_pos < *image_size) {
            *image = realloc(*image, (*image_size = image_pos));
            if (*image == NULL) {
                fprintf(stderr, "error reallocating memory for image\n");
                exit(EXIT_FAILURE);
            }
        }

        if (DEBUG)
            printf("is now image with %i bytes and pos %i\n", *image_size, image_pos);

        /* close stream */
        if (fclose(stream) < 0)
            fprintf(stderr, "parent: error closing stream\n");

        /* wait for child to finish */
        int status;
        waitpid(pid, &status, 0);
    }
}